package config

import java.io.File

import org.joda.time.DateTime
import play.api.libs.json.Json
import shapeless.ops.hlist.ToList
import shapeless.ops.record._
import shapeless.{HList, LabelledGeneric}
import shapeless.record._

/**
 * Created by Administrator on 2019/11/13
 */
trait MyListTool {

  implicit class MyList[T](list: List[T]) {

    def distinctBy[B](f: T => B) = {
      list.map { x =>
        (f(x), x)
      }.toMap.values.toList
    }

    def distinctByKeepHead[B](f: T => B): List[T] = {

      def loop(list: List[T], acc: (List[T], Set[B])): (List[T], Set[B]) = {
        list match {
          case Nil => acc
          case x :: xs =>
            val key = f(x)
            val (list, set) = acc
            if (!set.contains(key)) {
              loop(xs, (list ::: List(x), set + (key)))
            } else loop(xs, acc)
        }
      }

      loop(list, (List[T](), Set[B]()))._1
    }

    def lines[R <: HList, K <: HList, V <: HList](
                                                   implicit gen: LabelledGeneric.Aux[T, R], keys: Keys.Aux[R, K],
                                                   values: Values.Aux[R, V],
                                                   ktl: ToList[K, Symbol],
                                                   vtl: ToList[V, Any]
                                                 ) = {
      getLinesByTs(list)
    }

    def toTxtFile[R <: HList, K <: HList, V <: HList](file: File)(
      implicit gen: LabelledGeneric.Aux[T, R], keys: Keys.Aux[R, K],
      values: Values.Aux[R, V],
      ktl: ToList[K, Symbol],
      vtl: ToList[V, Any]
    ) = {
      getLinesByTs(list)
    }

    def getLinesByTs[T, R <: HList, K <: HList, V <: HList](ys: List[T])(
      implicit gen: LabelledGeneric.Aux[T, R], keys: Keys.Aux[R, K],
      values: Values.Aux[R, V],
      ktl: ToList[K, Symbol],
      vtl: ToList[V, Any]
    ) = {
      //age(15):::name(nt) age,name 15,nt
      val fieldNames = keys().toList.map(_.name)
      val lines = ys.map { y =>
        gen.to(y).values.toList.map{x=>
          getValue(x)
        }
      }
      fieldNames :: lines
    }

    def getValue[T](kind: T, noneMessage: String = ""): String = {
      kind match {
        case x if x.isInstanceOf[DateTime] => val time = x.asInstanceOf[DateTime]
          time.toString("yyyy-MM-dd HH:mm:ss")
        case x if x.isInstanceOf[Option[T]] => val option = x.asInstanceOf[Option[T]]
          if (option.isDefined) getValue(option.get, noneMessage) else noneMessage
        case x if x.isInstanceOf[Seq[T]] => val list = x.asInstanceOf[Seq[T]]
          list.mkString(";")
        case _ => kind.toString
      }
    }

    def getJsonByT[T, R <: HList](y: T)(implicit gen: LabelledGeneric.Aux[T, R],
                                        toMap: ToMap.Aux[R, Symbol, Any]) = {
      val map = gen.to(y).toMap.map { case (symbol, value) =>
        (symbol.name, getValue(value))
      }
      Json.toJson(map)
    }

  }


}
